package com.cxkj.scale_plugin;

import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import cn.com.scale.sdk.OnNewWeightListener;
import cn.com.scale.sdk.OnScaleConnectedListener;
import cn.com.scale.sdk.ScaleManager;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniModule;

public class ScaleModule extends UniModule {
    private static final String TAG = "ScaleModule";

    private final ScaleManager scaleManager = new ScaleManager();
    private boolean connected = false;

    private UniJSCallback eventCallback; // 用于持续监听重量变化
    private double lastWeight = -9999;
    private int lastStable = -1;
    // 精度常量映射
    private static final String[] ACCURACY_MAP = {
            "ACCURACY_001", "ACCURACY_002", "ACCURACY_005",
            "ACCURACY_010", "ACCURACY_020", "ACCURACY_050",
            "ACCURACY_100", "ACCURACY_200", "ACCURACY_500"
    };

    // 小数点位数映射
    private static final String[] RADIX_MAP = {
            "RADIX_POINT_0", "RADIX_POINT_1", "RADIX_POINT_2",
            "RADIX_POINT_3", "RADIX_POINT_4"
    };
    /**
     * 连接秤（仅调用一次回调）
     */
    @UniJSMethod(uiThread = true)
    public void connect(JSONObject options, UniJSCallback callback) {
        String port = options.getString("port");
        int baudRate = options.getIntValue("baudRate");

        scaleManager.connect(port, baudRate, new OnScaleConnectedListener() {
            @Override
            public void onConnected() {
                connected = true;
                callback.invoke(createSimpleResponse("connected"));

                // 设置重量监听器（此为持续回调）
                scaleManager.setOnNewWeightListener(onNewWeightListener);
            }

            @Override
            public void onDisconnected(int code, String desc) {
                connected = false;
                callback.invoke(createErrorResponse("disconnected", code, desc));
            }
        });
    }

    /**
     * 注册监听重量数据（持续回调）
     */
    @UniJSMethod(uiThread = true)
    public void onWeightChanged(UniJSCallback callback) {
        this.eventCallback = callback;
    }

    /**
     * 主动断开连接（仅调用一次回调）
     */
    @UniJSMethod(uiThread = true)
    public void disconnect(UniJSCallback callback) {
        try {
            scaleManager.disconnect();
            connected = false;
            callback.invoke(createSimpleResponse("disconnected"));
        } catch (Exception e) {
            Log.e(TAG, "disconnect error", e);
            callback.invoke(createError("disconnect_error", e.getMessage()));
        }
    }

    /**
     * 重量监听器（持续回调）
     */
    private final OnNewWeightListener onNewWeightListener = new OnNewWeightListener() {
        @Override
        public void onNewWeight(double weight, String unit, int stable) {
            if (weight == lastWeight && stable == lastStable && stable == 1) return;

            lastWeight = weight;
            lastStable = stable;

            JSONObject data = new JSONObject();
            data.put("weight", weight);
            data.put("unit", unit);
            data.put("stable", stable == 1);

            if (stable == -1) {
                data.put("message", "重量溢出或开机未归零");
            }

            if (eventCallback != null) {
                eventCallback.invokeAndKeepAlive(data);
            }
        }
    };
    /**
     * 置零操作
     */
    @UniJSMethod(uiThread = true)
    public void reset(UniJSCallback callback) {
        if (!connected) {
            callback.invoke(createError("not_connected", "Scale is not connected"));
            return;
        }

        try {
            scaleManager.reset();
            callback.invoke(createSimpleResponse("reset_success"));
        } catch (Exception e) {
            callback.invoke(createError("reset_failed", e.getMessage()));
        }
    }

    /**
     * 去皮操作
     */
    @UniJSMethod(uiThread = true)
    public void tare(UniJSCallback callback) {
        if (!connected) {
            callback.invoke(createError("not_connected", "Scale is not connected"));
            return;
        }

        try {
            scaleManager.tare();
            callback.invoke(createSimpleResponse("tare_success"));
        } catch (Exception e) {
            callback.invoke(createError("tare_failed", e.getMessage()));
        }
    }

    /**
     * 清除操作
     */
    @UniJSMethod(uiThread = true)
    public void clear(UniJSCallback callback) {
        if (!connected) {
            callback.invoke(createError("not_connected", "Scale is not connected"));
            return;
        }

        try {
            scaleManager.clear();
            callback.invoke(createSimpleResponse("clear_success"));
        } catch (Exception e) {
            callback.invoke(createError("clear_failed", e.getMessage()));
        }
    }

    /**
     * 设置负载标定
     */
    @UniJSMethod(uiThread = true)
    public void setStandardization(int stand, UniJSCallback callback) {
        if (!connected) {
            callback.invoke(createError("not_connected", "Scale is not connected"));
            return;
        }

        try {
            scaleManager.setStandardization(stand);
            callback.invoke(createSimpleResponse("standardization_set"));
        } catch (Exception e) {
            callback.invoke(createError("standardization_failed", e.getMessage()));
        }
    }

    /**
     * 设置最大称重
     */
    @UniJSMethod(uiThread = true)
    public void setMaxWeight(int max, UniJSCallback callback) {
        if (!connected) {
            callback.invoke(createError("not_connected", "Scale is not connected"));
            return;
        }

        if (max < 300 || max > 99999) {
            callback.invoke(createError("invalid_value", "Max weight must be between 300 and 99999"));
            return;
        }

        try {
            scaleManager.setMaxWeight(max);
            callback.invoke(createSimpleResponse("max_weight_set"));
        } catch (Exception e) {
            callback.invoke(createError("max_weight_failed", e.getMessage()));
        }
    }

    /**
     * 设置分度值
     */
    @UniJSMethod(uiThread = true)
    public void setAccuracy(String accuracy, UniJSCallback callback) {
        if (!connected) {
            callback.invoke(createError("not_connected", "Scale is not connected"));
            return;
        }

        try {
            int accuracyValue = getAccuracyValue(accuracy);
            scaleManager.setAccuracy(accuracyValue);
            callback.invoke(createSimpleResponse("accuracy_set"));
        } catch (Exception e) {
            callback.invoke(createError("accuracy_failed", e.getMessage()));
        }
    }

    /**
     * 设置小数点位数
     */
    @UniJSMethod(uiThread = true)
    public void setRadixPoint(String radix, UniJSCallback callback) {
        if (!connected) {
            callback.invoke(createError("not_connected", "Scale is not connected"));
            return;
        }

        try {
            int radixValue = getRadixValue(radix);
            scaleManager.setRadixPoint(radixValue);
            callback.invoke(createSimpleResponse("radix_set"));
        } catch (Exception e) {
            callback.invoke(createError("radix_failed", e.getMessage()));
        }
    }

    // --------------------
    // 工具函数
    // --------------------

    private JSONObject createSimpleResponse(String status) {
        JSONObject res = new JSONObject();
        res.put("status", status);
        return res;
    }

    private JSONObject createErrorResponse(String status, int code, String desc) {
        JSONObject res = new JSONObject();
        res.put("status", status);
        res.put("code", code);
        res.put("message", desc);
        return res;
    }

    private JSONObject createError(String status, String message) {
        JSONObject res = new JSONObject();
        res.put("status", status);
        res.put("error", message);
        return res;
    }
    // --------------------
    // 工具函数
    // --------------------

    private int getAccuracyValue(String accuracy) throws IllegalArgumentException {
        for (int i = 0; i < ACCURACY_MAP.length; i++) {
            if (ACCURACY_MAP[i].equals(accuracy)) {
                return i + 1; // 因为ACCURACY_001 = 1
            }
        }
        throw new IllegalArgumentException("Invalid accuracy value");
    }

    private int getRadixValue(String radix) throws IllegalArgumentException {
        for (int i = 0; i < RADIX_MAP.length; i++) {
            if (RADIX_MAP[i].equals(radix)) {
                return i; // RADIX_POINT_0 = 0
            }
        }
        throw new IllegalArgumentException("Invalid radix value");
    }
}